<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Document</title>
    <script src="../vue.js"></script>
  </head>

  <body>
    <div id="app"></div>
    <script>
      /* 
      diff算法分析:
        * diff算法是什么?diff就是比较新旧两颗虚拟DOM树,寻找差异的算法,引入diff算法源码中是使用patch函数来完成的,所以也有人称作patch算法
        * diff算法总体的比较思路:采用深度优先,同级比较的方式
        * 当组件内部依赖的响应式数据发生更新的时候,就会运行Vue内部的updateComponent函数
          - 运行_render方法,生成新的虚拟DOM树(vnode)
          - 把新的虚拟DOM数 vnode 传递到 _update方法 中,比较新旧两颗DOM树,并完成DOM更新
        * 在update函数中,可以拿到vm上_vnode属性,就是旧的虚拟DOM
          - 首先定义一个oldVnode保存旧的虚拟DOM
          - 再给vm的_vnode更新为新的虚拟DOM
          - 使用patch函数进行新旧虚拟DOM两颗树的比较
        * patch函数首先对根节点比较是否相同(相同:两个虚拟DOM节点的标签类型相同[input元素还要比较type],并且key值也相同,如果没有书写key,则key默认是undefined),在vue源码中有一个sameVnode方法专门用来比较是否相同的
          - 如果比较相同则进入更新流程(1.将旧节点的真实DOM赋值给新节点,复用  2.对比新旧节点的属性是否相同,有变化的则会更新到真实DOM中, 3. 当前节点新旧DOM处理完成,开始比较子节点)
          - 如果比较不相同,则新节点深层次递归创建新元素,旧节点删除元素
        * 比较子节点
          - vue使用两个指针分别指向新旧节点的头和尾
          - 首先对比新旧树头指针,判断是否相同,如果相同则进入更新流程,然后采用深度优先递归比较新旧节点的子节点
          - 继续比较两个头指针,如果不相同则比较新旧树的尾指针,如果相同则进入更新流程....
          - 比较头尾指针是否相同,如果相同则进入更新流程
          - 如果上边的规则不符合,就会以新树的头指针为基准,循环旧的虚拟dom节点,如果存在则直接拿过来复用进入更新流程,如果找不到则直接以新树当前节点创建一个新的真实DOM
          - 当头指针超过尾指针的时候,比较结束,如果旧树中还有剩余节点,则删除这个剩余节点
    */

      /* 
      简洁版diff算法流程：
        * 当组件创建和更新的时候，vue会执行内部的update函数，该函数使用render函数生成的虚拟DOM树,将新旧DOM树进行比较找到差异,并更新真实DOM
        * 对比的过程被称作diff,vue内部使用patch函数完成对比过程
        * 在对比的时候,vue采用深度优先,同级比较的方式
        * 在比较的时候,通过虚拟DOM的key和tag来判断是否相同的
        * 第一:先对根节点的新旧虚拟DOM进行对比,如果相同则将旧节点复用,然后更新数据,递归比较子节点,如果不同则直接根据新的虚拟DOM递归创建新的节点,并且删除旧的DOM
        * 第二:比较子节点,首先vue给新旧虚拟DOM都使用了两个指针,分别指向头尾,然后不断向中间靠拢进行对比,提高对比性能,在比较的过程中如果发现相同则进入更新流程,否则新增和移除dom
        * 按照上边的两点一致递归,直到整个DOM对比完成
    
    
    */

      function Vue() {
        const updateComponent = () => {
          this._update(this._render());
        };
      }

      function _update(_vnode) {
        //首先把旧的vnode保存起来
        const oldVnode = vm._vnode;
        //把新的虚拟DOM交给vm
        vm._vnode = _vnode;

        //调用patch函数,进行新旧虚拟DOM的比较
        patch();
      }

      const vm = new Vue({
        el: "#app",
        data() {
          return {};
        },
      });
    </script>
  </body>
</html>
